package com.openlogic.common.logic.run;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.commons.lang3.StringUtils;
import org.noear.nami.Nami;
import org.noear.solon.Solon;
import org.noear.solon.core.event.AppBeanLoadEndEvent;
import org.noear.solon.core.event.EventListener;

import com.alibaba.fastjson2.JSON;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.AviatorEvaluatorInstance;
import com.openlogic.api.logic.dto.RuleSqlModelDto;
import com.openlogic.api.logic.service.RemoteRuleModelService;
import com.openlogic.common.core.exception.ServiceException;
import com.openlogic.common.core.utils.DateUtils;
import com.openlogic.common.logic.cache.DefaultSqlCache;
import com.openlogic.common.logic.constants.RuleConstants;
import com.openlogic.common.logic.node.enums.NodeExecEnums;
import com.openlogic.common.logic.node.factory.NodeExecFactory;
import com.openlogic.common.logic.utils.NumericRegxUtils;
import com.openlogic.common.plugins.db.api.utils.DataSourceUtils;
import com.openlogic.common.plugins.spi.enums.DbType;
import com.openlogic.datasource.api.param.ConnectionParam;

import jodd.db.connection.ConnectionProvider;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
* @ClassName: ExecRuleHandler
* @Description: 规则执行器
* @author weiyongpeng
* @date 2024年7月17日 上午9:01:07
 */
public abstract class ExecRuleHandler implements EventListener<AppBeanLoadEndEvent>{
	
	private static RemoteRuleModelService remoteRuleModelService = Solon.context().getBean(RemoteRuleModelService.class);

	protected abstract JSONObject typeRun(JSONArray resultArray1,JSONArray nodeArray,JSONArray lineArray,JSONObject inputjson,JSONArray areaArray,String areaFirst,String ruleId,StringBuffer reason,Map<String,Object> map);

	 /**
     * 默认缓存5分钟
     */
	protected static long DEFAULT_EXPIRE = 5 * 60 * 1000;
    
	protected static DefaultSqlCache sqlCache = new DefaultSqlCache(100, DEFAULT_EXPIRE);

	static {
		if (remoteRuleModelService == null) {
			remoteRuleModelService = Nami.builder().create(RemoteRuleModelService.class);
			Solon.context().beanMake(RemoteRuleModelService.class);
		}
	}
	
    protected <T> T putCacheValue(String key, T value, long ttl) {
        sqlCache.put(key, value, ttl);
        return value;
    }
	
	protected abstract JSONObject recRunForNode(JSONArray resultArray1, JSONArray nodeArray, JSONArray lineArray,
			JSONObject inputjson, JSONArray areaArray, String areaFirst, String ruleId, StringBuffer reason,
			Map<String, Object> map);
	
	/**
	* 描述：规则执行解析
	* @Title: runAndGetResult
	* @param resValue 解析后的json规则串
	* @param parmInfo 入参
	* @param reason 执行条件临时变量
	* @param map 规则属性Map
	* @return
	* @author weiyongpeng
	* @date  2024年7月18日 下午3:01:37
	 */
	@SuppressWarnings("rawtypes")
	public String runAndGetResult(String resValue, String parmInfo, StringBuffer reason, Map<String, Object> map) {
		// 原始json数据
		JSONObject resJson = JSONObject.fromObject(resValue);
		// 入参数据
		JSONObject inputjson = JSONObject.fromObject(parmInfo);
		Map<Object,Object> inParam = new HashMap<>();
		for (Object ijo : inputjson.entrySet()){
	    	if(!((Map.Entry)ijo).getKey().toString().equals("everyNodeList") && !((Map.Entry)ijo).getKey().toString().equals("areaInfo") ) {
	    		inParam.put(((Map.Entry)ijo).getKey().toString().replaceAll("\"", ""), ((Map.Entry)ijo).getValue().toString().replaceAll("\"", ""));
	    	}
	    }
		JSONArray nodeArray = new JSONArray();
		JSONArray lineArray = new JSONArray();
		JSONArray areaArray = new JSONArray();
		String ruleId = "";
		// 节点部分
		nodeArray = JSONObject.fromObject(resJson.getString("NodeInfo")).getJSONArray("Value");
		// 连线部分
		lineArray = JSONObject.fromObject(resJson.getString("LineInfo")).getJSONArray("Value");
		// 循环部分
		areaArray = JSONObject.fromObject(resJson.getString("AreaInfo")).getJSONArray("Value");
		// 规则块Id
		if (resJson.getString("ruleId") != null) {
			ruleId = resJson.getString("ruleId");
		}
		JSONObject reJson = new JSONObject();

		JSONArray resultArrayTmp = new JSONArray();
		JSONArray lineArrayTmp = new JSONArray();
		// 开始执行时间
		Date startDate = DateUtils.getNowDate();
		JSONArray everyNodeList = new JSONArray();
		JSONObject startNode = new JSONObject();
		// start节点
		for (int i = 0, nodeArraylength = nodeArray.size(); i < nodeArraylength; i++) {
			for (int j = 0, lineArraylength = lineArray.size(); j < lineArraylength; j++) {
				// 获取节点
				resultArrayTmp = (JSONArray) nodeArray.get(i);
				// 定位start节点开始执行
				if (resultArrayTmp.get(5).equals("start")) {
					// 获取连线
					lineArrayTmp = (JSONArray) lineArray.get(j);
					if (lineArrayTmp.get(0).equals(
							resultArrayTmp.get(7).toString().replace("[", "").replace("]", "").replace("\"", ""))) {
						// 为了减少循环
						nodeArray.remove(i);
						lineArray.remove(j);
						startNode.put("ruleId", "");
						startNode.put("nodeId", "0");
						startNode.put("startExecTime", DateUtils.formatDate(startDate, DateUtils.YYYY_MM_DD_HH_MM_SS));
						startNode.put("nodeTypeName", "规则流:【执行】");
						everyNodeList.add(startNode);
						inputjson.put("everyNodeList", everyNodeList);
						// 迭代往下执行
						inputjson = getEveryNodeList(inputjson, lineArrayTmp.get(0).toString(),
								resultArrayTmp.get(2).toString(), resultArrayTmp.get(0).toString(), ruleId, 0, reason, map, startDate,inParam,null);
						reJson = recRun(lineArrayTmp.get(4).toString(), inputjson, nodeArray, lineArray, areaArray, "",
								ruleId, reason, map);
						return reJson.toString();
					}
				}
			}
		}
		return null;
	}
	
	/**
	* 描述：节点调试重新组装运行结果
	* @Title: changeEveryNodeList
	* @param resultStr
	* @param reason
	* @return
	* @author weiyongpeng
	* @date  2024年7月20日 上午8:18:07
	 */
	public String changeEveryNodeList(String resultStr,StringBuffer reason){
		JSONArray everyNodeListArrayNew = new JSONArray();
		JSONObject reJson = JSONObject.fromObject(resultStr);
		String everyNodeListStr = reJson.get("everyNodeList").toString();
		JSONArray everyNodeListArray = new JSONArray();
		everyNodeListArray = JSONArray.fromObject(everyNodeListStr);
		for(int i=0;i<everyNodeListArray.size();i++) {
			String ruleId = ((JSONObject)(everyNodeListArray.get(i))).get("ruleId").toString();
			if("".equals(ruleId)) {
				JSONObject everyNodeList = (JSONObject)everyNodeListArray.get(i);
				everyNodeList = getEveryNodeList(everyNodeList,everyNodeListArray);
				everyNodeListArrayNew.add(everyNodeList);
			}
		}
		reJson.put("everyNodeList", everyNodeListArrayNew.toString());
		reJson.put("reason", reason.toString().equals("")?"":reason.toString().substring(0, reason.length()-1));
		return reJson.toString();
	}
	
	/**
	* 描述：迭代执行 
	* @Title: recRun
	* @param nodeId 节点ID
	* @param inputjson 传入参数
	* @param nodeArray 节点数组
	* @param lineArray 连线数组
	* @param areaArray 循环数组
	* @param areaFirst 循环第一个节点Id
	* @param ruleId
	* @param reason
	* @param map
	* @return
	* @author weiyongpeng
	* @date  2024年7月17日 上午9:03:17
	 */
	@SuppressWarnings("rawtypes")
	protected JSONObject recRun(String nodeId,JSONObject inputjson,JSONArray nodeArray,JSONArray lineArray,JSONArray areaArray,String areaFirst,String ruleId,StringBuffer reason,Map<String,Object> map) {
		Map<Object,Object> inParam = new HashMap<>();
		for (Object ijo : inputjson.entrySet()){
	    	if(!((Map.Entry)ijo).getKey().toString().equals("everyNodeList") && !((Map.Entry)ijo).getKey().toString().equals("areaInfo") ) {
	    		inParam.put(((Map.Entry)ijo).getKey(), ((Map.Entry)ijo).getValue());
	    	}
	    }
		// 开始执行时间
		Date startDate = DateUtils.getNowDate();
		JSONObject reJson = new JSONObject();
		JSONArray nodeArrayTmp = new JSONArray();
		boolean areaResult = false;
		for(int i=0,nodeArraylength=nodeArray.size();i<nodeArraylength;i++) {
			nodeArrayTmp =(JSONArray) nodeArray.get(i);
			if(nodeArrayTmp.get(0).equals(nodeId)) {//定位到对应节点
				if(nodeArrayTmp.get(2).equals("area")) {//判断节点是否在循环块中
					if(isTop(nodeArrayTmp.get(4).toString(),areaArray)) {//判断是否是top类型
						if(nodeArrayTmp.get(0).toString().equals(areaFirst)) {//判断是不是第一个节点
							areaResult = isAreaTrue(nodeArrayTmp,inputjson,areaArray,reason);//判断是否满足条件
							if(areaResult) {
								reJson = NodeExecFactory.getInvokeStrategyMap(nodeArrayTmp.get(5).toString()).typeRun(nodeArrayTmp,nodeArray,lineArray,inputjson,areaArray,areaFirst,ruleId,reason,map);
							}else {
								JSONArray lineArray1 = new JSONArray();
								for(int j=0,lineArraylength=lineArray.size();j<lineArraylength;j++) {
									 lineArray1 =(JSONArray) lineArray.get(j);
									 if(lineArray1.get(0).toString().contains("line_"+nodeArrayTmp.get(4).toString())) {
										 inputjson = getEveryNodeList(inputjson,lineArray1.get(0).toString(),nodeArrayTmp.get(2).toString(),nodeArrayTmp.get(0).toString(),ruleId,0,reason,map,startDate,inParam,null);
										 reJson = recRun(lineArray1.get(4).toString(),inputjson,nodeArray,lineArray,areaArray,"",ruleId,reason,map);
										 return reJson;
									 }
								}
							}
						}else {
							reJson = NodeExecFactory.getInvokeStrategyMap(nodeArrayTmp.get(5).toString()).typeRun(nodeArrayTmp,nodeArray,lineArray,inputjson,areaArray,areaFirst,ruleId,reason,map);
						}
					}else {
						reJson = NodeExecFactory.getInvokeStrategyMap(nodeArrayTmp.get(5).toString()).typeRun(nodeArrayTmp,nodeArray,lineArray,inputjson,areaArray,areaFirst,ruleId,reason,map);
					}	
				}else {
					// 非循环节点走到这里
					reJson = NodeExecFactory.getInvokeStrategyMap(nodeArrayTmp.get(5).toString()).typeRun(nodeArrayTmp,nodeArray,lineArray,inputjson,areaArray,areaFirst,ruleId,reason,map);
				}
			}
		}
		return reJson;
	}
	
	/**
	* 描述：轨迹list
	* @Title: getAreaInfoList
	* @param inputjson
	* @param nodeId
	* @return
	* @author weiyongpeng
	* @date  2024年7月24日 下午3:19:57
	 */
	protected JSONObject getAreaInfoList(JSONObject inputjson,String nodeId) {
		JSONObject AreaInfo = new JSONObject();
		JSONArray AreaInfoList = new JSONArray();
		JSONArray everyNodeList = new JSONArray();
		if(inputjson.get("areaInfo")!=null) {
			AreaInfo= (JSONObject) inputjson.get("areaInfo");
			AreaInfoList = (JSONArray) AreaInfo.get(nodeId);
			if(AreaInfoList==null) {
				AreaInfoList = new JSONArray();
			}
		}
		if(inputjson.get("everyNodeList")!=null) {
			everyNodeList= (JSONArray) inputjson.get("everyNodeList");
		}
		inputjson.remove("areaInfo");
		inputjson.remove("areaFirst");
		inputjson.remove("everyNodeList");
		AreaInfoList.add(inputjson);
		AreaInfo.put(nodeId, AreaInfoList);
		inputjson.put("areaInfo", AreaInfo);
		inputjson.put("everyNodeList", everyNodeList);
		return inputjson;
	}
	
	protected JSONObject getEveryNodeList(JSONObject everyNodeList,JSONArray everyNodeListArray) {
		JSONObject reJsonNew = new JSONObject();
		JSONObject everyNodeListNew = new JSONObject();
		String nodeId = everyNodeList.get("nodeId").toString();
		for(int i=0;i<everyNodeListArray.size();i++) {
			String ruleId = ((JSONObject)(everyNodeListArray.get(i))).get("ruleId").toString();
			if(ruleId.equals(nodeId)) {
				reJsonNew = (JSONObject)(everyNodeListArray.get(i));
				everyNodeListNew = getEveryNodeList(reJsonNew,everyNodeListArray);
				((JSONArray)(everyNodeList.get("childList"))).add(everyNodeListNew) ;
			}
		}
		return everyNodeList;
	}

	/**
	* 描述：获取每一个节点数据 everyNodeList
	* @Title: getEveryNodeList
	* @param inputjson
	* @param nextLineId
	* @param type
	* @param nodeId
	* @param ruleId
	* @param index
	* @param reason 条件执行结果：原因
	* @param map 规则变量属性Map
	* @param startDate 开始时间
	* @param outParam  出参
	* @param inParam   入参
	* @return everyNodeList
	* @author weiyongpeng
	* @date  2024年7月20日 上午8:18:49
	 */
	protected JSONObject getEveryNodeList(JSONObject inputjson, String nextLineId, String type, String nodeId,
			String ruleId, int index, StringBuffer reason, Map<String, Object> map, Date startDate, Map<Object, Object> inParam, Map<Object, Object> outParam) {
		// 结束执行时间
		Date endDate = DateUtils.getNowDate();
		String endExecuateTime = DateUtils.formatDate(endDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
		String startExecuateTime = DateUtils.formatDate(startDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
		JSONArray everyNodeList = new JSONArray();
		JSONObject AreaInfo = new JSONObject();
		JSONObject everyNode = new JSONObject();
		JSONArray childList = new JSONArray();
		if (inputjson.get("everyNodeList") != null) {
			everyNodeList = (JSONArray) inputjson.get("everyNodeList");
		}
		if (inputjson.get("areaInfo") != null) {
			AreaInfo = (JSONObject) inputjson.get("areaInfo");
		}
		String truelist = "";
		if (inputjson.get("trueRowList") != null) {
			truelist = inputjson.get("trueRowList").toString();
		} else {
		}
		inputjson.remove("areaFirst");
		inputjson.remove("trueRowList");
		inputjson.remove("everyNodeList");
		inputjson.remove("areaInfo");
		everyNode.put("nodeName", "");
		if (index != -1) {
			everyNode.put("flag", true);
		} else {
			everyNode.put("flag", false);
		}
		everyNode.put("data", inputjson);
		everyNode.put("loop", false);
		everyNode.put("index", index);// 修改
		everyNode.put("nextLineId", nextLineId);
		everyNode.put("type", type);
		everyNode.put("nodeId", nodeId);
		everyNode.put("ruleId", ruleId);
		everyNode.put("childList", childList);
		everyNode.put("trueRowList", truelist);
		everyNode.put("nodeTypeName", "节点:【" + NodeExecEnums.find(type).getDesc() + "】");
		//everyNode.put("inParam", inParam != null && !inParam.isEmpty() ? "入参为:【" + JSON.toJSONString(inParam) + "】" : "入参为空:【-】");
		if(inParam != null && !inParam.isEmpty()) {
			everyNode.put("inParam", "入参为:【" + inParam + "】");
		}
		//everyNode.put("outParam", outParam != null && !outParam.isEmpty() ? "执行结果为:【" + JSON.toJSONString(outParam) + "】" : "执行结果为空:【-】");
		if(outParam != null && !outParam.isEmpty()) {
			everyNode.put("outParam", "执行结果为:【" + outParam + "】");
		}
		if(reason != null && StringUtils.isNotBlank(reason.toString()) && !type.equals(NodeExecEnums.RESULT_NODE.getCode()) && !type.equals(NodeExecEnums.COMMON_NODE.getCode()) && !type.equals(NodeExecEnums.START_NODE.getCode())) {
			everyNode.put("reason", "执行依据为:【" + reason.substring(0,reason.length()-1) + "】");
		}
		everyNode.put("startExecTime", startExecuateTime);
		everyNode.put("endExecTime", endExecuateTime);
		everyNode.put("execTotalTimeMills", "耗时: "+(endDate.getTime() - startDate.getTime())+" 毫秒");
		everyNode.put("execStatus", RuleConstants.NODE_EXEC_SUCCESS);
		everyNodeList.add(everyNode);
		inputjson.put("everyNodeList", everyNodeList);
		inputjson.put("areaInfo", AreaInfo);
		return inputjson;
	}
	
	protected JSONObject getEveryNodeListThrow(JSONObject inputjson, String nextLineId, String type, String nodeId,
			String ruleId, int index, StringBuffer reason, Map<String, Object> map, Date startDate, Map<Object, Object> inParam, JSONObject errorJson) {
		// 结束执行时间
		Date endDate = DateUtils.getNowDate();
		String endExecuateTime = DateUtils.formatDate(endDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
		String startExecuateTime = DateUtils.formatDate(startDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
		JSONArray everyNodeList = new JSONArray();
		JSONObject AreaInfo = new JSONObject();
		JSONObject everyNode = new JSONObject();
		JSONArray childList = new JSONArray();
		if (inputjson.get("everyNodeList") != null) {
			everyNodeList = (JSONArray) inputjson.get("everyNodeList");
		}
		if (inputjson.get("areaInfo") != null) {
			AreaInfo = (JSONObject) inputjson.get("areaInfo");
		}
		String truelist = "";
		if (inputjson.get("trueRowList") != null) {
			truelist = inputjson.get("trueRowList").toString();
		} else {
		}
		inputjson.remove("areaFirst");
		inputjson.remove("trueRowList");
		inputjson.remove("everyNodeList");
		inputjson.remove("areaInfo");
		everyNode.put("nodeName", "");
		if (index != -1) {
			everyNode.put("flag", true);
		} else {
			everyNode.put("flag", false);
		}
		everyNode.put("data", inputjson);
		everyNode.put("loop", false);
		everyNode.put("index", index);// 修改
		everyNode.put("nextLineId", nextLineId);
		everyNode.put("type", type);
		everyNode.put("nodeId", nodeId);
		everyNode.put("ruleId", ruleId);
		everyNode.put("childList", childList);
		everyNode.put("trueRowList", truelist);
		everyNode.put("nodeTypeName", "节点:【" + NodeExecEnums.find(type).getDesc() + "】");
		if(inParam != null && !inParam.isEmpty()) {
			everyNode.put("inParam", "入参为:【" + inParam + "】");
		}
		if(errorJson != null && !errorJson.isEmpty()) {
			everyNode.put("errorMsg", "异常信息为:【" + errorJson + "】");
		}
		everyNode.put("startExecTime", startExecuateTime);
		everyNode.put("endExecTime", endExecuateTime);
		everyNode.put("execTotalTimeMills", "耗时: "+(endDate.getTime() - startDate.getTime())+" 毫秒");
		everyNode.put("execStatus", RuleConstants.NODE_EXEC_ERROR);
		everyNodeList.add(everyNode);
		inputjson.put("everyNodeList", everyNodeList);
		inputjson.put("areaInfo", AreaInfo);
		return inputjson;
	}
	
	/**
	* 描述：判断循环类型
	* @Title: isTop
	* @param id 循环块ID
	* @param areaArray 循环部分
	* @return
	* @author weiyongpeng
	* @date  2024年7月17日 上午9:06:45
	 */
	protected boolean isTop(String id, JSONArray areaArray) {
		JSONArray areaArray1 = new JSONArray();
		for (int i = 0, areaArrayLength = areaArray.size(); i < areaArrayLength; i++) {
			areaArray1 = (JSONArray) areaArray.get(i);
			if (areaArray1.get(0).equals(id)) {
				if (areaArray1.get(2).equals("top")) {
					return true;
				} else {
					return false;
				}
			}
		}
		return true;
	}
	
	/**
	 * 判断条件是否成立
	 * @param  resultArray1   当前节点
	 * @param  inputjson   单签值
	 * @param  areaArray   循环部分 
	 * @param reason 
	 * @param count 
	 * */
	@SuppressWarnings("unchecked")
	public boolean isAreaTrue(JSONArray resultArray1,JSONObject inputjson,JSONArray areaArray, StringBuffer reason) {
		boolean result=true;
		JSONArray areaArray1 = new JSONArray();
		//执行循环判断
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine se = manager.getEngineByName("js");
		String valStringOld = "";
		for(int i = 0,areaArrayLength=areaArray.size();i<areaArrayLength;i++) {
			areaArray1 = (JSONArray)areaArray.get(i);
			if(areaArray1.get(0).equals(resultArray1.get(4))) {
				String res = "";
				String decValue = "";
				res = areaArray1.get(3).toString();
				String[] reslist =  res.split("&@");
				for(int l=0,reslistlength=reslist.length;l<reslistlength;l++) {
					if(reslist[l].equals("1#")) {
						decValue += "&&";
					}else if(reslist[l].equals("2#")){
						decValue += "||";
					}else {
							String reslist1 = reslist[l].replaceAll("#", "");
							valStringOld = reslist1;
							Iterator<String> it2 = inputjson.keys(); 
							while(it2.hasNext()){
								// 获得key
								String key = it2.next(); 
								//特别注意数字不带单引号，字符串带单引号
								reslist1 = reslist1.replaceAll(key, NumericRegxUtils.isDecimal(inputjson.getString(key))?inputjson.getString(key):"'"+inputjson.getString(key)+"'");
								valStringOld = valStringOld.replaceAll(key, NumericRegxUtils.isNumber(inputjson.getString(key))?inputjson.getString(key) : "'"+ inputjson.getString(key)+"'");
							}
							decValue = decValue+reslist1;
					}
				}
				try {						
					result = (Boolean)se.eval(decValue);
					if(result) {
						reason = reason.append("满足：").append(valStringOld).append(",");
					}else {
						reason = reason.append("不满足：").append(valStringOld).append(",");
					}
					return result;
				} catch (ScriptException e) {
					e.printStackTrace();
				}
			}
	    }
		return result;
	}
	
	/**
	* 描述：参数排序
	* @Title: sortJson
	* @param inputjson
	* @return
	* @author weiyongpeng
	* @date  2024年7月17日 上午10:32:48
	 */
	@SuppressWarnings("unchecked")
	public JSONObject sortJson(JSONObject inputjson) {
		JSONObject reJsonNew = new JSONObject();
		String[] inputjsonArray = new String[inputjson.size()]; 
		Iterator<String> it1 = inputjson.keys(); 
		int a=0;
		while(it1.hasNext()){
			// 获得key
			String key = it1.next(); 
			inputjsonArray[a]=key;
			a++;
		}
		for(int i = 0;i<inputjsonArray.length-1;i++) {
			for(int j = 0; j<inputjsonArray.length-1-i;j++) {
				if(inputjsonArray[j+1].length()>inputjsonArray[j].length()) {
					String temp = inputjsonArray[j];
					inputjsonArray[j]=inputjsonArray[j+1];
					inputjsonArray[j+1] = temp;
				}
			}
		}
		for(int k = 0;k<inputjsonArray.length;k++) {
			reJsonNew.put(inputjsonArray[k], inputjson.get(inputjsonArray[k]));
		}
		return reJsonNew;
	}
	
	/**
	 * 寻找下一节点
	 * @param  resultArray1   当前node节点
	 * @param  nodeArray   node节点集合
	 * @param  lineArray   连线数组
	 * @param  inputjson   当前传入参数
	 * @param  areaArray   循环部分
	 * @param  areaFirst   循环第一个节点Id
	 * @param startDate    开始时间
	 * @param outParam 	   出参
	 * @param inParam 	   入参
	 * @return  reJson  当前参数对应真实值  
	 * */
	protected JSONObject runNextNode(JSONArray resultArray1,JSONArray nodeArray,JSONArray lineArray,JSONObject inputjson,JSONArray areaArray,String areaFirst,String ruleId,int index,StringBuffer reason,Map<String,Object> map, Date startDate, Map<Object, Object> inParam, Map<Object, Object> outParam) {
		JSONArray lineArray1 = new JSONArray();
		JSONObject reJson = new JSONObject();
		boolean areaResult = false;
		//当前是否是循环节点
		if(!resultArray1.get(2).equals("area")) {//非循环节点
			for(int j=0,lineArraylength=lineArray.size();j<lineArraylength;j++) {
				 lineArray1 =(JSONArray) lineArray.get(j);
				 if(lineArray1.get(0).equals(resultArray1.get(7).toString().replace("[", "").replace("]", "").replace("\"", ""))) {
					 inputjson = getEveryNodeList(inputjson,lineArray1.get(0).toString(),resultArray1.get(2).toString(),resultArray1.get(0).toString(),ruleId,index,reason,map,startDate,inParam,outParam);
					 reJson = recRun(lineArray1.get(4).toString(),inputjson,nodeArray,lineArray,areaArray,areaFirst,ruleId,reason,map);
					 return reJson;
				 }
			}
			inputjson = getEveryNodeList(inputjson,"",resultArray1.get(2).toString(),resultArray1.get(0).toString(),ruleId,index,reason,map,startDate,inParam,outParam);
			inputjson.remove("areaFirst");
			reJson = inputjson;
		}else {
			if(resultArray1.get(7).toString().equals("[]")) {//判断是否是当前循环最后节点
				if(isTop(resultArray1.get(4).toString(),areaArray)) {//判断循环类型
					//跳到循环第一节点
					inputjson = getAreaInfoList(inputjson,resultArray1.get(0).toString());
					reJson = recRun(areaFirst,inputjson,nodeArray,lineArray,areaArray,areaFirst,ruleId,reason,map);
				    return reJson;
				}else {
					areaResult = isAreaTrue(resultArray1,inputjson,areaArray,reason);//判断是否满足条件
					if(areaResult) {
						//跳到循环第一节点
						inputjson = getAreaInfoList(inputjson,resultArray1.get(0).toString());
						reJson = recRun(areaFirst,inputjson,nodeArray,lineArray,areaArray,areaFirst,ruleId,reason,map);
					    return reJson;
					}else {
						lineArray1 = new JSONArray();
						inputjson = getAreaInfoList(inputjson,resultArray1.get(0).toString());
						for(int j=0,lineArraylength=lineArray.size();j<lineArraylength;j++) {
							 lineArray1 =(JSONArray) lineArray.get(j);
							 if(lineArray1.get(0).toString().contains("line"+resultArray1.get(4).toString())) {
								 inputjson = getEveryNodeList(inputjson,lineArray1.get(0).toString(),resultArray1.get(2).toString(),resultArray1.get(0).toString(),ruleId,index,reason,map,startDate,inParam,outParam);
								 reJson = recRun(lineArray1.get(4).toString(),inputjson,nodeArray,lineArray,areaArray,"",ruleId,reason,map);
								 return reJson;
							 }
						}
					}
				}	    
			}else {
				for(int j=0,lineArraylength=lineArray.size();j<lineArraylength;j++) {
					 lineArray1 =(JSONArray) lineArray.get(j);
					 if(lineArray1.get(0).equals(resultArray1.get(7).toString().replace("[", "").replace("]", "").replace("\"", ""))) {
						 inputjson = getEveryNodeList(inputjson,lineArray1.get(0).toString(),resultArray1.get(2).toString(),resultArray1.get(0).toString(),ruleId,index,reason,map,startDate,inParam,outParam);
						 reJson = recRun(lineArray1.get(4).toString(),inputjson,nodeArray,lineArray,areaArray,areaFirst,ruleId,reason,map);
						 return reJson;
					 }
				}
			}
			
		}
		return reJson;
	}
	
	/**
	* 描述：异常抛出执行节点
	* @Title: runNextNodeThrow
	* @param resultArray1
	* @param nodeArray
	* @param lineArray
	* @param inputjson
	* @param areaArray
	* @param areaFirst
	* @param ruleId
	* @param index
	* @param reason
	* @param map
	* @param startDate
	* @param inParam
	* @param errorJson
	* @return
	* @author weiyongpeng
	* @date  2024年9月23日 下午2:18:21
	 */
	protected JSONObject runNextNodeThrow(JSONArray resultArray1,JSONArray nodeArray,JSONArray lineArray,JSONObject inputjson,JSONArray areaArray,String areaFirst,String ruleId,int index,StringBuffer reason,Map<String,Object> map, Date startDate, Map<Object, Object> inParam, JSONObject errorJson) {
		JSONArray lineArray1 = new JSONArray();
		JSONObject reJson = new JSONObject();
		boolean areaResult = false;
		//当前是否是循环节点
		if(!resultArray1.get(2).equals("area")) {//非循环节点
			for(int j=0,lineArraylength=lineArray.size();j<lineArraylength;j++) {
				 lineArray1 =(JSONArray) lineArray.get(j);
				 if(lineArray1.get(0).equals(resultArray1.get(7).toString().replace("[", "").replace("]", "").replace("\"", ""))) {
					 inputjson = getEveryNodeListThrow(inputjson,"",resultArray1.get(2).toString(),resultArray1.get(0).toString(),ruleId,index,reason,map,startDate,inParam,errorJson);
					 reJson = inputjson;
					 return reJson;
				 }
			}
			inputjson = getEveryNodeListThrow(inputjson,"",resultArray1.get(2).toString(),resultArray1.get(0).toString(),ruleId,index,reason,map,startDate,inParam,errorJson);
			inputjson.remove("areaFirst");
			reJson = inputjson;
		}else {
			if(resultArray1.get(7).toString().equals("[]")) {//判断是否是当前循环最后节点
				if(isTop(resultArray1.get(4).toString(),areaArray)) {//判断循环类型
					//跳到循环第一节点
					inputjson = getAreaInfoList(inputjson,resultArray1.get(0).toString());
					reJson = recRun(areaFirst,inputjson,nodeArray,lineArray,areaArray,areaFirst,ruleId,reason,map);
					//reJson = inputjson;
				    return reJson;
				}else {
					areaResult = isAreaTrue(resultArray1,inputjson,areaArray,reason);//判断是否满足条件
					if(areaResult) {
						//跳到循环第一节点
						inputjson = getAreaInfoList(inputjson,resultArray1.get(0).toString());
						reJson = recRun(areaFirst,inputjson,nodeArray,lineArray,areaArray,areaFirst,ruleId,reason,map);
					    return reJson;
					}else {
						lineArray1 = new JSONArray();
						inputjson = getAreaInfoList(inputjson,resultArray1.get(0).toString());
						for(int j=0,lineArraylength=lineArray.size();j<lineArraylength;j++) {
							 lineArray1 =(JSONArray) lineArray.get(j);
							 if(lineArray1.get(0).toString().contains("line"+resultArray1.get(4).toString())) {
								 inputjson = getEveryNodeListThrow(inputjson,"",resultArray1.get(2).toString(),resultArray1.get(0).toString(),ruleId,index,reason,map,startDate,inParam,errorJson);
								 //reJson = recRun(lineArray1.get(4).toString(),inputjson,nodeArray,lineArray,areaArray,"",ruleId,reason,map);
								 reJson = inputjson;
								 return reJson;
							 }
						}
					}
				}	    
			}else {
				for(int j=0,lineArraylength=lineArray.size();j<lineArraylength;j++) {
					 lineArray1 =(JSONArray) lineArray.get(j);
					 if(lineArray1.get(0).equals(resultArray1.get(7).toString().replace("[", "").replace("]", "").replace("\"", ""))) {
						 inputjson = getEveryNodeListThrow(inputjson,"",resultArray1.get(2).toString(),resultArray1.get(0).toString(),ruleId,index,reason,map,startDate,inParam,errorJson);
						 // reJson = recRun(lineArray1.get(4).toString(),inputjson,nodeArray,lineArray,areaArray,areaFirst,ruleId,reason,map);
						 reJson = inputjson;
						 return reJson;
					 }
				}
			}
			
		}
		return reJson;
	}
	
	/**
	* 描述：根据sql参数的key查询sql参数的结果集
	* @Title: selectRuleSqlParamRes
	* @param inputjson
	* @param se
	* @param key
	* @author weiyongpeng
	* @param env 
	* @throws SQLException 
	* @date  2024年12月3日 下午4:05:36
	 */
	@SuppressWarnings("unchecked")
	protected List<Map<String,Object>> selectRuleSqlParamRes(JSONObject inputjson, String key, Map<String, Object> env) throws SQLException {
		String sqlexp;
		// 1、查询sql语句，并执行sql select SQLEXP FROM CONFIG WHERE NAME = ${name}; 所以决策入参正常传递
		RuleSqlModelDto sqlInfoMap = remoteRuleModelService.listRuleModelInner(key).getData();
		String dbType = sqlInfoMap.getDbType();
		ConnectionParam connectionParam = JSON.parseObject(sqlInfoMap.getConnectionParams(), ConnectionParam.class);
		sqlexp = sqlInfoMap.getSqlexp();
		Iterator<String> its = inputjson.keys();
		if(sqlexp.contains("${")) { // 如果有条件参数
			while (its.hasNext()) {
				String key2 = its.next(); 
				if(!key2.equals("everyNodeList") && !key2.equals("areaInfo")) {
					String tmp = "\\$\\{" + key2 + "\\}";
					sqlexp = sqlexp.replaceAll(tmp , "'"+inputjson.getString(key2)+"'");
				}
			}
		}
		// 执行sql获取结果json
		ConnectionProvider connectionProvider = DataSourceUtils.getJdbcTemplate(DbType.getDbType(dbType), connectionParam);
		PreparedStatement prepareStatement = connectionProvider.getConnection().prepareStatement(sqlexp);
		// 2、转化结果集为json 调用字符串的函数 决策设置需要标识出sql参数 加一个#标识 并缓存
		String sqlStr = (String) Optional.ofNullable(sqlCache.get(key))
										.orElse(putCacheValue(key, JSON.toJSONString(prepareStatement.executeQuery(sqlexp)), DEFAULT_EXPIRE));
		// se.put(key, sqlStr);
		env.put(key, sqlStr);
		return (List<Map<String,Object>>) com.alibaba.fastjson.JSONArray.parse((String)sqlCache.get(key));
	}
	
	/**
	* 描述：aviator执行判断
	* @Title: selectRuleSqlParamResByAviator
	* @param inputjson
	* @param key
	* @param data
	* @return
	* @author weiyongpeng
	* @throws SQLException 
	* @date  2024年12月6日 下午4:59:22
	 */
	@SuppressWarnings("unchecked")
	protected String selectRuleSqlParamResByAviator(JSONObject inputjson, String key, JSONObject data, Boolean isContainsColumn, Map<String,Object> map) throws SQLException {
		String sqlexp;
		if (isContainsColumn) {
			String[] sqlVars = key.split("\\.");
			// 分解sql参数key和columnname
			String columnName = sqlVars[1];
			String sqlKey = sqlVars[0];
			// 1、查询sql语句，并执行sql select SQLEXP FROM CONFIG WHERE NAME = ${name}; 所以决策入参正常传递
			RuleSqlModelDto sqlInfoMap = remoteRuleModelService.listRuleModelInner(sqlKey).getData();
			String dbType = sqlInfoMap.getDbType();
			ConnectionParam connectionParam = JSON.parseObject(sqlInfoMap.getConnectionParams(), ConnectionParam.class);
			sqlexp = sqlInfoMap.getSqlexp();
			Iterator<String> its = inputjson.keys();
			if (sqlexp.contains("${")) { // 如果有条件参数
				while (its.hasNext()) {
					String key2 = its.next();
					if (!key2.equals("everyNodeList") && !key2.equals("areaInfo")) {
						String tmp = "\\$\\{" + key2 + "\\}";
						sqlexp = sqlexp.replaceAll(tmp, "'" + inputjson.getString(key2) + "'");
					}
				}
			}
			// 执行sql获取结果json
			ConnectionProvider connectionProvider = DataSourceUtils.getJdbcTemplate(DbType.getDbType(dbType), connectionParam);
			PreparedStatement prepareStatement = connectionProvider.getConnection().prepareStatement(sqlexp);
			// 2、转化结果集为json 调用字符串的函数 决策设置需要标识出sql参数 加一个#标识 并缓存
			String sqlStr = (String) Optional.ofNullable(sqlCache.get(key))
					.orElse(putCacheValue(key, JSON.toJSONString(prepareStatement.executeQuery(sqlexp)), DEFAULT_EXPIRE));
			List<Map<String,Object>> listObjectFir = (List<Map<String,Object>>) com.alibaba.fastjson.JSONArray.parse(sqlStr);
			List<Object> columnValueList = listObjectFir.stream().filter(mapF -> Optional.ofNullable(mapF.get(columnName)).isPresent()).map(mapV -> {
				Object value = mapV.get(columnName);
				return value;
			}).collect(Collectors.toList());
			// 表达式
			String formula = data.get("formula").toString();
			formula = formula.replaceAll("@"+key+"@", key.replaceAll("\\.", ""));
			map.put(key.replaceAll("\\.", ""), JSON.toJSONString(columnValueList));
			return formula;
		}else {
			// 1、查询sql语句，并执行sql select SQLEXP FROM CONFIG WHERE NAME = ${name}; 所以决策入参正常传递
			RuleSqlModelDto sqlInfoMap = remoteRuleModelService.listRuleModelInner(key).getData();
			String dbType = sqlInfoMap.getDbType();
			ConnectionParam connectionParam = JSON.parseObject(sqlInfoMap.getConnectionParams(), ConnectionParam.class);
			sqlexp = sqlInfoMap.getSqlexp();
			Iterator<String> its = inputjson.keys();
			if (sqlexp.contains("${")) { // 如果有条件参数
				while (its.hasNext()) {
					String key2 = its.next();
					if (!key2.equals("everyNodeList") && !key2.equals("areaInfo")) {
						String tmp = "\\$\\{" + key2 + "\\}";
						sqlexp = sqlexp.replaceAll(tmp, "'" + inputjson.getString(key2) + "'");
					}
				}
			}
			// 执行sql获取结果json
			ConnectionProvider connectionProvider = DataSourceUtils.getJdbcTemplate(DbType.getDbType(dbType), connectionParam);
			PreparedStatement prepareStatement = connectionProvider.getConnection().prepareStatement(sqlexp);
			// 2、转化结果集为json 调用字符串的函数 决策设置需要标识出sql参数 加一个#标识 并缓存
			String sqlStr = (String) Optional.ofNullable(sqlCache.get(key))
					.orElse(putCacheValue(key, JSON.toJSONString(prepareStatement.executeQuery(sqlexp)), DEFAULT_EXPIRE));
			// 表达式
			map.put(key, sqlStr);
			return data.get("formula").toString();
		}
	}
	
	/**
	* 描述：分割sql参数字符串
	* @Title: extractStrings
	* @param input
	* @return
	* @author weiyongpeng
	* @date  2024年12月4日 下午4:04:07
	 */
	public static Set<String> extractStrings(String input) {
        Set<String> extractedStrings = new LinkedHashSet<>();
        // 正则表达式匹配 @...@
        Pattern pattern = Pattern.compile("@(.*?)@");
        Matcher matcher = pattern.matcher(input);
        while (matcher.find()) {
            extractedStrings.add(matcher.group(1)); // 返回 @...@ 中间的内容
        }
        return extractedStrings; // 返回所有匹配的字符串
    }

	/**
	* 描述：统计异常信息
	* @Title: getErrorMsg
	* @param resultJson
	* @return
	* @author weiyongpeng
	* @date  2024年9月23日 下午2:17:01
	 */
	public long getErrorMsg(String resultJson) {
		return resultJson.contains("errorMsg") ? 1 : 0;
	}
	
	/**
	* 描述：校验表达式
	* @Title: checkExpression
	* @param expression
	* @author weiyongpeng
	* @date  2024年12月27日 上午8:09:54
	 */
	protected void checkExpression(String expression) {
        // 事件表达式校验
        AviatorEvaluatorInstance engine = AviatorEvaluator.getInstance();
        try {
            engine.validate(expression);
        } catch (Exception e) {
            throw new ServiceException("表达式错误！");
        }
    }
}
